package cn.fastpay.core.security;

import cn.fastpay.core.util.RSAUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.interfaces.RSAPublicKey;
import java.util.Collections;


/**
 * @author freewolf
 */
public class UserJwtAuthorizationFilter extends BasicAuthenticationFilter {

    public UserJwtAuthorizationFilter(AuthenticationManager authManager) {
        super(authManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res,
                                    FilterChain chain) throws IOException, ServletException {
        String header = req.getHeader(UserSecurityConstant.HEADER_STRING);
        if (header == null || !header.startsWith(UserSecurityConstant.TOKEN_PREFIX)) {
            chain.doFilter(req, res);
            return;
        }

        UsernamePasswordAuthenticationToken authentication = getAuthentication(header, req);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        chain.doFilter(req, res);
    }

    private UsernamePasswordAuthenticationToken getAuthentication(String token, HttpServletRequest req) {
        // 从Application中取出公钥
        RSAPublicKey publicKey = (RSAPublicKey) req.getServletContext().getAttribute("publicKey");
        if (publicKey == null) {
            publicKey = RSAUtil.getPublicKey("public_key.pem");
            req.getServletContext().setAttribute("publicKey", publicKey);
        }

        Claims claims = Jwts.parser().setSigningKey(publicKey)
                .parseClaimsJws(token.replace(UserSecurityConstant.TOKEN_PREFIX, "")).getBody();

        String username = claims.getSubject();
        // token 无效
        if (StringUtils.isBlank(username)) return null;

        return new UsernamePasswordAuthenticationToken(username, null, Collections.emptyList());
    }
}
